import type { SearchSelectorConfig } from '../index'
import type { PageSearchMetaSourceConfig, PageSearchMetaTimeConfig } from './index'
import { StyleModule } from '../../../../../../lib/abstract'
import { PageManager } from '../../../../../../lib/abstract/page_manager'
import { ThemeVarService } from '../../../../../../lib/abstract/style/theme_var/service'
import { IconService } from '../../../../../../lib/icons'
import { PageHandler } from '../../../../../../lib/page_handler'
import { BaiduPageType } from '../../../../../../lib/page_handler/platform/baidu/types'
import { ToolKit } from '../../../../../../lib/utils/toolkit'
import {
  AppStyleCollections,
  HOSTNAME,
  logger,
  MODULE_CONFIG,
  OpenSourcePlatform,
  SUPPORTED_PLATFORMS,
} from '../../../../../../types/constants'
import {
  BADGE_ELEMENT_STYLES,
  BADGE_STYLES,
} from '../../../../../../types/constants/styles/badge'
import { POPULAR_LINKS } from '../../../../../../types/constants/web_link'
import { ConfigManager } from '../../../../../config_manager'
import { AppModule } from '../../../../../config_manager/types'
import { AutoPagination } from '../../../../interaction/auto_pagination'
import { SearchStyle } from './index'

export interface TitleIconConfig {
  selector: string
  title: string
  avatarContainer: string
  avatar: string
}

export class BaiduStyle extends StyleModule {
  private readonly name: string = 'BaiduStyle'
  private static instance: BaiduStyle
  private pageManager: PageManager = PageManager.getInstance()
  private pageHandler: PageHandler = PageHandler.getInstance()
  private iconService: IconService = IconService.getInstance()
  private searchStyle: SearchStyle = SearchStyle.getInstance()
  private readonly themeVarService: ThemeVarService = ThemeVarService.getInstance()
  private observer: MutationObserver | null = null
  private videoObserver: MutationObserver | null = null
  private readonly pageType = this.pageHandler.pages.baidu.pageType
  private readonly selectors: SearchSelectorConfig = this.pageHandler.pages.baidu.getResultSelectors()
  private readonly maskId: string = '_mask'
  private readonly pageLoaderId: string = MODULE_CONFIG.COMPONENTS.pageLoader.id

  constructor() {
    super()

    if (HOSTNAME !== SUPPORTED_PLATFORMS.BAI_DU)
      return

    this.init()
  }

  /**
   * 初始化
   */
  init(): void {
    this.initDynamicStyleObserver()
    this.initVideoObserver()
    this.initResultMeta()
    this.beautyTitle()
    this.updateSearchStyle()
  }

  /**
   * 处理分页样式
   */
  handlePageNumStyle(): void {}

  /**
   * 获取单例实例
   */
  public static getInstance(): BaiduStyle {
    if (!BaiduStyle.instance) {
      BaiduStyle.instance = new BaiduStyle()
    }
    return BaiduStyle.instance
  }

  /**
   * 初始化动态样式观察器
   */
  private initDynamicStyleObserver() {
    // 如果已经存在观察器，先断开
    this.stopObservation()

    // 遮罩观察器
    this.observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation.type === 'childList' && mutation.removedNodes.length > 0) {
          if (Array.from(mutation.removedNodes).some(n => (n as Element).id === this.maskId)) {
            logger.attention(`[${this.name}] 搜索结果已更新`)
            this.handleMaskRemoved()
          }
          if (Array.from(mutation.removedNodes).some(n => (n as Element).id === this.pageLoaderId)) {
            logger.attention(`[${this.name}] 分页结果已更新`)
            this.handlePageLoaderRemoved()
          }
        }
      })
    })

    // 监听变化
    this.observer.observe(document.body, {
      childList: true, // 只需要直接子元素变化
      subtree: false,
    })
  }

  /**
   * 初始化视频元素观察器
   */
  private initVideoObserver() {
    if (this.pageType !== BaiduPageType.Video)
      return

    const container = document.querySelector(this.selectors.container)

    if (!container) {
      logger.warn(`[${this.name}] 视频列表容器未找到：${this.selectors.container}`)
      return
    }

    // 单次批量处理（替代多次微任务）
    const processBatch = (nodes: NodeList) => {
      const videos = Array.from(nodes).filter(
        node => node.nodeType === Node.ELEMENT_NODE
          && (node as Element).matches(this.selectors.selector),
      )

      if (videos.length > 0) {
        ToolKit.advanced.performance.doubleRAF(() => this.applyVideoUpdate())
      }
    }

    // 遮罩观察器
    this.videoObserver = new MutationObserver((mutations) => {
      const addedNodes = mutations.flatMap(m =>
        Array.from(m.addedNodes).filter(n => n.nodeType === Node.ELEMENT_NODE),
      )

      if (addedNodes.length > 0) {
        processBatch(addedNodes as unknown as NodeList)
      }
    })

    // 监听变化
    this.videoObserver.observe(container, {
      childList: true, // 只需要直接子元素变化
      subtree: false,
    })
  }

  applyVideoUpdate(): void {
    this.initResultMeta()
  }

  /**
   * 停止观察
   */
  stopObservation(): void {
    this.observer?.disconnect()
    this.observer = null
    this.videoObserver?.disconnect()
    this.videoObserver = null
  }

  /**
   * 初始化搜索样式
   */
  updateSearchStyle(forceUpdate?: boolean): void {
    const supportPages = [
      BaiduPageType.Web,
      BaiduPageType.News,
      BaiduPageType.Video,
    ]

    this.searchStyle.setBaseStyle(this.selectors, { supportPages, forceUpdate })
  }

  /**
   * 初始化结果元数据
   */
  initResultMeta(): void {
    const baseSourceConfig = {
      base: {
        selector: '.cosc-source-text',
        container: '[class^="source-container-pc"], [class*="source-container"], .cosc-source',
      },
      footer: {
        selector: '[data-module="footer"][class*="source"] .sc-avatar + div:contains("中经数据")',
        container: '[data-module="footer"][class*="source"]',
      },
      life: {
        selector: this.generateLifeSelectors(),
        container: '[data-module="lgsoe"][class*="source"]',
      },
      move: {
        selector: '.source-container a[data-module="source"] .sc-avatar + div:contains("猫眼电影")',
        container: '.source-container',
      },
      train: {
        selector: ':is(.op-ly_ticket_train-footer, .op-map_flight-footer) .c-showurl',
        container: ':is(.op-ly_ticket_train-footer, .op-map_flight-footer)',
      },
      xueShu: {
        selector: '.op-xueshu-links-source .c-showurl',
        container: '.op-xueshu-links-source',
      },
      news: {
        selector: '[class^="news-source"] :is(div, a) .c-color-gray',
        container: '[class^="news-source"]',
      },
      other: {
        selector: '.c-row[class*="source"] :is(div, a) .c-color-gray',
        container: '.c-row[class*="source"]',
      },
    }

    const sourceConfig: PageSearchMetaSourceConfig = {
      [BaiduPageType.Web]: baseSourceConfig,
      [BaiduPageType.News]: baseSourceConfig,
      [BaiduPageType.Video]: {
        base: {
          selector: '.wetSource',
          container: 'div:has(> .wetSource)',
          cleanFunc: (text: string) => text.replace(/来源：/, '').trim(),
          enableIcon: true,
        },
      },
    }

    const timeConfig: PageSearchMetaTimeConfig = {
      [BaiduPageType.Web]: {
        selector: '[data-module="abstract"] .cos-color-text-minor',
        excludeText: ['最佳答案'],
      },
      [BaiduPageType.News]: {
        selector: '.c-span-last .c-gap-right-xsmall',
      },
      [BaiduPageType.Video]: {
        selector: 'div:has(> .wetSource) span:not(.wetSource)',
        cleanFunc: (text: string) => text.replace(/发布时间：/, '').trim(),
      },
    }

    this.searchStyle.createResultMeta(
      this.selectors.selector,
      {
        leftConfig: sourceConfig,
        rightConfig: timeConfig,
      },
    )
  }

  /**
   * 生成生活选择器
   */
  generateLifeSelectors(): string {
    const lifeKeywords = [
      '惠生活',
      '百度本地生活',
      '百度文库',
    ]
    return lifeKeywords.map(
      item => `[data-module="lgsoe"][class*="source"] a div:contains("${item}")`,
    ).join(',')
  }

  /**
   * 美化标题
   */
  beautyTitle(): void {
    switch (this.pageType) {
      case BaiduPageType.Web:
        this.beautyWebTitle()
        break
      case BaiduPageType.News:
        this.beautyNewTitle()
        break
    }
  }

  /**
   * 美化网页标题
   */
  beautyWebTitle(): void {
    $(this.selectors.selector).each((_index, element) => {
      const $element = $(element)
      const $titleTag = $element.find(`[class^="title-wrapper"] .sc-tag, .cosc-title .cos-tag`)

      this.updateBg($element, $titleTag)
      this.addTitleIcon($element)
    })
  }

  /**
   * 美化资讯标题
   */
  beautyNewTitle(): void {
    $(this.selectors.selector).each((_index, element) => {
      const $element = $(element)

      this.addTitleIcon($element)
    })
  }

  /**
   * 更新背景颜色
   */
  updateBg($element: JQuery<HTMLElement>, $titleTag: JQuery<HTMLElement>): void {
    const muValue = $element.attr('mu') || ''

    const hasSpecialTag = ['官方', '权威'].includes($titleTag.text())
    const isProjectRootLink = this.isOpenSourceProjectRootLink(muValue)
    const isPopularLink = this.isPopularLink(muValue)

    if (isProjectRootLink) {
      this.addOpenSourceProjectTag($element)
    }

    if (hasSpecialTag || isProjectRootLink) {
      $element[0].style.setProperty('background', `var(${this.themeVarService.search.resultItem.backgroundOfficial})`, 'important')
    }

    if (isPopularLink) {
      $element[0].style.setProperty('background', `var(${this.themeVarService.search.resultItem.backgroundPopular})`, 'important')
    }
  }

  /**
   * 判断是否为 GitHub/Gitee 等开源项目根链接
   */
  isOpenSourceProjectRootLink(url: string): boolean {
    return /^https:\/\/(?:github|gitee)\.com\/[^/]+\/[^/]+\/?$/.test(url)
  }

  /**
   * 判断是否为热门网站链接
   */
  isPopularLink(url: string): boolean {
    const isSystemPopularWeb = Object.values(POPULAR_LINKS).some(
      platform => Object.values(platform).some(link => link === url || url.startsWith(link)),
    )

    const customPopularWeb = this.pageManager.getPopularLink().split('\n').filter(Boolean)
    const isCustomPopularWeb = customPopularWeb.some(link => link === url || url.startsWith(link))

    return isSystemPopularWeb || isCustomPopularWeb
  }

  /**
   * 添加开源项目标签
   */
  addOpenSourceProjectTag($element: JQuery<HTMLElement>): void {
    const muValue = $element.attr('mu') || ''
    const platform = this.getOpenSourcePlatform(muValue)
    const $container = $element.find('[class*="title-box"]:has(> h3)')

    this.pageHandler.features.badge.addBadge(
      $container,
      platform,
      `${platform === OpenSourcePlatform.Unknown ? '' : `${ToolKit.string.capitalizeFirstLetter(platform)} `}项目`,
      {
        backgroundColor: BADGE_STYLES.primary,
        elementStyle: BADGE_ELEMENT_STYLES.default,
      },
    )
  }

  /**
   * 获取开源项目类型
   */
  getOpenSourcePlatform(url: string): OpenSourcePlatform {
    if (!url || typeof url !== 'string') {
      return OpenSourcePlatform.Unknown
    }

    const githubMatch = url.match(/^https:\/\/github\.com/)
    if (githubMatch) {
      return OpenSourcePlatform.Github
    }

    const giteeMatch = url.match(/^https:\/\/gitee\.com/)
    if (giteeMatch) {
      return OpenSourcePlatform.Gitee
    }

    return OpenSourcePlatform.Unknown
  }

  /**
   * 添加标题图标
   */
  addTitleIcon($element: JQuery<HTMLElement>): void {
    const config: Partial<Record<BaiduPageType, TitleIconConfig>> = {
      [BaiduPageType.Web]: {
        selector: '.cosc-source .cosc-source-link',
        title: '[class^="title-wrapper"] h3',
        avatarContainer: '.cos-avatar',
        avatar: '.cos-avatar-img',
      },
      [BaiduPageType.News]: {
        selector: '[class^="news-source"] [class^="source-link"]',
        title: 'h3[class^="news-title"]',
        avatarContainer: '.c-img',
        avatar: '[class^="source-img"]',
      },
    }

    const pageConfig = config[this.pageType as BaiduPageType]

    if (!pageConfig)
      return

    if (!this.hasPlatformIcon($element, pageConfig)) {
      this.useSystemIcon($element, pageConfig)
    }
    else {
      this.usePlatformIcon($element, pageConfig)
    }
  }

  /**
   * 判断是否有平台图标
   */
  hasPlatformIcon($element: JQuery<HTMLElement>, pageConfig: TitleIconConfig): boolean {
    const $source = $element.find(pageConfig.selector)
    const $avatarContainer = $source.find(pageConfig.avatarContainer)

    const sourceAvatar = $avatarContainer.find(pageConfig.avatar).attr('src') || ''

    return Boolean(sourceAvatar)
  }

  /**
   * 使用系统图标
   */
  useSystemIcon($element: JQuery<HTMLElement>, pageConfig: TitleIconConfig): void {
    const $titleContainer = $element.find(pageConfig.title)

    // 检查是否已存在图标
    if ($titleContainer.hasClass(AppStyleCollections.Icon.LINK_ICON))
      return

    const muValue = $element.attr('mu') || ''
    const iconConfig = this.iconService.api.icons.link.find(item =>
      ToolKit.string.isMatch(muValue, item.match?.link || ''),
    )

    if (!iconConfig)
      return

    $titleContainer.addClass(`${AppStyleCollections.Icon.LINK_ICON} ${IconService.getIconClass(iconConfig.id)}`)
  }

  /**
   * 使用平台图标
   */
  usePlatformIcon($element: JQuery<HTMLElement>, pageConfig: TitleIconConfig): void {
    const $titleContainer = $element.find(pageConfig.title)

    // 检查是否已存在图标
    if ($titleContainer.find('.title-icon').length > 0)
      return

    const $source = $element.find(pageConfig.selector)

    if (!$source || $source.length === 0)
      return

    const sourceLink = $source.attr('href') || ''
    const $avatarContainer = $source.find(pageConfig.avatarContainer)
    const sourceAvatar = $avatarContainer.find(pageConfig.avatar).attr('src')

    if (!sourceLink || !sourceAvatar)
      return

    const $titleIcon = $(`
      <a class="title-icon" target="_blank" rel="noopener noreferrer" href="${sourceLink}">
        <img src="${sourceAvatar}" alt="Source Icon" height="18" width="18" style="border-radius: 50% !important;">
      </a>
    `)

    $titleContainer.prepend($titleIcon)

    // 隐藏原来的图标
    $avatarContainer.hide()
  }

  applyUpdate(): void {
    $('#content_right').hide()
    this.markElement.markBaiduElements(this.pageType)
    this.initResultMeta()
    this.beautyTitle()
    this.hideElements()
    this.updateSearchStyle()
  }

  /**
   * 处理遮罩移除事件
   */
  private handleMaskRemoved(): void {
    this.applyUpdate()

    // 启用自动分页
    const status = ConfigManager.getInstance().getFeatureEnabled(AppModule.AutoPagination.id)

    if (status) {
      const autoPagination = AutoPagination.getInstance()
      autoPagination.destroy()
      autoPagination.core()
    }
  }

  /**
   * 处理分页器移除事件
   */
  handlePageLoaderRemoved(): void {
    this.applyUpdate()
  }

  /**
   * 停止监听变化
   */
  disconnectThemeObserver(): void {
    this.observer?.disconnect()
    this.observer = null
  }
}
